home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 January: Mac OS SDK / Dev.CD Jan 00 SDK1.toast / Development Kits / Mac OS / RAVE Starter Samples / Callback Sample / Gouraud Callback.cp next >
Encoding:
Text File  |  1998-04-30  |  8.0 KB  |  267 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************
  2.  
  3. Gouraud Triangles.cp
  4. Author: Timothy Carroll
  5. Apple Developer Technical Support
  6. timc@apple.com
  7.  
  8. Modification History: 
  9.  
  10. 5/1/98    TMC     Initial Release
  11.  
  12. Copyright © 1998 Apple Computer, Inc., All Rights Reserved
  13.  
  14. You may incorporate this sample code into your applications without
  15. restriction, though the sample code has been provided "AS IS" and the
  16. responsibility for its operation is 100% yours.  However, what you are
  17. not permitted to do is to redistribute the source as "DSC Sample Code"
  18. after having made changes. If you're going to re-distribute the source,
  19. we require that you make it clear in the source that the code was
  20. descended from Apple Sample Code, but that you've made changes.
  21. *************************************************************************************/
  22.  
  23. #include <RAVE.h>
  24. #include <QD3DAcceleration.h>  // We need this for engine gestalt codes
  25. #include "Common Stuff.h"
  26. #include "RAVE Utilities.h"
  27.  
  28. const UInt16 kRGB16WhitePixel = 0xFFFF;
  29.  
  30. // Standard declarations
  31. void main (void);
  32. void DoRAVEWindow(void);
  33.  
  34. void RAVEComposite (
  35.     const TQADrawContext    *drawContext,    /* Draw context */
  36.     const TQADevice            *buffer,            /* TQADevice describing back                                                                 buffer */
  37.     const TQARect            *dirtyRect,        /* Minimum area to process;                                                                 NULL means whole buffer */
  38.     void                    *refCon);                    /* user define parameter */
  39.  
  40.  
  41. void main (void)
  42. {
  43.     // do standard mac init
  44.     InitGraf(&qd.thePort);
  45.     InitFonts();
  46.     InitWindows();
  47.     InitMenus();
  48.     TEInit();
  49.     InitDialogs(nil);
  50.     InitCursor();
  51.  
  52.     MaxApplZone();
  53.     MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters(); MoreMasters();
  54.  
  55.     // Initialize the SIN and COS lookup tables (see RAVE Utilities.cp)
  56.     if (InitializeLookups() == noErr)
  57.         DoRAVEWindow();
  58. }
  59.  
  60.  
  61. // This is a simple RAVE callback sample.  it sets every other pixel in a checkerboard pattern to white.
  62.  
  63.  
  64. void RAVEComposite (
  65.     const TQADrawContext    *drawContext,    /* Draw context */
  66.     const TQADevice            *buffer,        /* TQADevice describing back                                                                 buffer */
  67.     const TQARect            *dirtyRect,        /* Minimum area to process;                                                                 NULL means whole buffer */
  68.     void                    *refCon)        /* user define parameter */
  69. {
  70. #pragma unused (drawContext)
  71. #pragma unused (dirtyRect)
  72. #pragma unused (refCon)
  73.  
  74.  
  75.     Boolean                 drawPixel = false;
  76.     TQADeviceMemory            const *memory = NULL;
  77.     UInt16                    *pixelPtr = NULL;
  78.     Ptr                        rowPtr = NULL;
  79.     long                    loopX, loopY, width, height, offset;
  80.     
  81.     memory = &buffer->device.memoryDevice;
  82.  
  83.     // buffer is a memory device, check to make sure we're using the right pixel type.
  84.     if ((memory->pixelType != kQAPixel_RGB16) &&
  85.         (memory->pixelType != kQAPixel_ARGB16))
  86.         return;
  87.         
  88.     rowPtr = (Ptr) memory->baseAddr;
  89.     width = memory->width;
  90.     height = memory->height;
  91.     offset = memory->rowBytes;
  92.     
  93.     for (loopY = 0; loopY < height; loopY++)
  94.     {
  95.         drawPixel = !drawPixel; // This should alternate by row;
  96.         pixelPtr = (UInt16 *) rowPtr;
  97.         rowPtr += offset;
  98.     
  99.         for (loopX = 0; loopX < width; loopX++)
  100.         {
  101.             drawPixel = !drawPixel;
  102.             if (drawPixel)
  103.                 *pixelPtr = kRGB16WhitePixel;
  104.             pixelPtr++;
  105.         }
  106.     }
  107.     
  108. }
  109.  
  110.  
  111.  
  112.  
  113. void DoRAVEWindow(void)
  114. {
  115.     // These hold our errors
  116.     OSErr            theErr = noErr;
  117.     TQAError        theQAErr = kQANoErr;
  118.     
  119.     // These hold the window and device we'll put on the screen
  120.     GDHandle        device = NULL;
  121.     WindowRef        theWindow = NULL;
  122.     
  123.     // We try to center the window on the device.
  124.     Rect            bounds = {0,0,320,320};
  125.     Rect            deviceRect;
  126.     
  127.     // We use these parameters to describe our environment to RAVE
  128.     TQADevice        qaDevice;
  129.     TQARect         qaBoundsRect;
  130.     
  131.     // we get these items back from RAVE
  132.     TQAEngine         *theEngine = NULL;
  133.     TQADrawContext    *theContext = NULL;
  134.     
  135.     // We use these in our drawing loop to create our RAVE animation.
  136.     int             loop = 0;
  137.     TQAVGouraud     theTriangle[3];
  138.     
  139.     // Notification method
  140.     TQANoticeMethod noticeMeth;
  141.     
  142.     RgnHandle        gray;
  143.     Rect            grayRect;
  144.     
  145.     
  146.     // First, grab the first monitor with the deepest display
  147.     gray = GetGrayRgn();
  148.     grayRect = (**gray).rgnBBox;
  149.     device = GetMaxDevice(&grayRect);
  150.     FAIL_NIL (device, "\pERROR: No monitors found")
  151.     
  152.  
  153.     // Center our bounds in the middle of the screen.
  154.     deviceRect = (**device).gdRect;
  155.  
  156.     OffsetRect (&bounds,
  157.                     (deviceRect.right+deviceRect.left-bounds.right)/2,
  158.                     (deviceRect.bottom+deviceRect.top-bounds.bottom)/2);
  159.     
  160.     // Create a Window to hold the RAVE information.
  161.         
  162.     theWindow = NewCWindow(NULL, &bounds, "\pRAVE Window", true, zoomDocProc, (WindowRef) -1, false, 0);
  163.     FAIL_NIL (theWindow, "\pERROR: Couldn't create RAVE Window")
  164.     
  165.     SetPortWindowPort (theWindow);
  166.     
  167.     // Next we need to find a RAVE engine and then build a DrawContext to draw into it.  First, we'll find
  168.     // an engine that is capable of drawing to the selected GDevice.
  169.  
  170.     qaDevice.deviceType = kQADeviceGDevice;
  171.     qaDevice.device.gDevice = device;
  172.     
  173.     // We have to explicitly enable the Apple hardware card because it isn't 100% RAVE compliant.
  174.     // If we use this engine, we have to write special case code to deal with it.
  175. #if qEnableAppleHardware
  176.     QAEngineEnable (kQAVendor_Apple,kQAEngine_AppleHW);
  177. #endif
  178.     
  179.     // We'll just grab the first engine that the system offers us.
  180.  
  181.     theEngine = QADeviceGetFirstEngine (&qaDevice);
  182.     FAIL_NIL (theEngine, "\pERROR:  No RAVE engines available.")
  183.     
  184.     // Next we need to set up the a QARect with the Window's rectangle in GDevice local coordinates.
  185.     
  186.     qaBoundsRect.left = bounds.left - deviceRect.left;
  187.     qaBoundsRect.right = bounds.right  - deviceRect.left;
  188.     qaBoundsRect.top = bounds.top - deviceRect.top;
  189.     qaBoundsRect.bottom = bounds.bottom - deviceRect.top;
  190.  
  191.     // If we wanted to create a clipping region, we'd do it here
  192.     
  193.     // Finally, we're ready to create the draw context!
  194.     theQAErr = QADrawContextNew (&qaDevice, &qaBoundsRect, NULL, theEngine, 
  195.                                  kQAContext_DeepZ | kQAContext_DoubleBuffer, &theContext);
  196.     if (theQAErr != kQANoErr) SIGNAL_ERROR("\pERROR:  Failed to create RAVE draw context")
  197.     FAIL_NIL (theContext, "\pERROR:  Failed to create RAVE draw context")
  198.     
  199.  
  200.     // QASetNotificationMethod was barfing when I pass in RAVEComposite directly.  I think it can't
  201.     // tell how to cast it because the notification method is a Union.  So now, I set up a variable
  202.     // to hold the union and explictly set RAVEComposite as a buffering method.  Works fine.
  203.     noticeMeth.bufferNoticeMethod = RAVEComposite;
  204.     
  205.     theQAErr = QASetNoticeMethod (theContext, kQAMethod_BufferComposite, noticeMeth ,NULL);
  206.     if (theQAErr != kQANoErr) SIGNAL_ERROR("\pERROR:  Failed to set compositing completion proc")
  207.     
  208.     // set the background to black
  209.     QASetFloat (theContext, kQATag_ColorBG_a, 1.0);
  210.     QASetFloat (theContext, kQATag_ColorBG_r, 0.0);
  211.     QASetFloat (theContext, kQATag_ColorBG_g, 0.0);
  212.     QASetFloat (theContext, kQATag_ColorBG_b, 0.0);
  213.     
  214.     // Finally, everything is ready!  We'll create an animated sequence and end it when the user
  215.     // presses a button.
  216.     
  217.  
  218.     while (!Button())
  219.     {
  220.     // Set up our points
  221.     theTriangle[0].x = 160 + 150*gCosArray[loop];
  222.     theTriangle[0].y = 160 + 150*gSinArray[loop];
  223.     theTriangle[0].z = 0.25;
  224.     theTriangle[0].invW = 1.0;
  225.     theTriangle[0].a = 1;
  226.     theTriangle[0].r = 1.0;
  227.     theTriangle[0].g = 0.0;
  228.     theTriangle[0].b = 0.0;
  229.     
  230.     theTriangle[1].x = 160 + 150*gCosArray[(loop+240) % 720];
  231.     theTriangle[1].y = 160 + 150*gSinArray[(loop+240) % 720];
  232.     theTriangle[1].z = 0.25;
  233.     theTriangle[1].invW = 1.0;
  234.     theTriangle[1].a = 1;
  235.     theTriangle[1].r = 0.0;
  236.     theTriangle[1].g = 1.0;
  237.     theTriangle[1].b = 0.0;    
  238.     
  239.     theTriangle[2].x = 160 + 150*gCosArray[(loop+480) % 720];
  240.     theTriangle[2].y = 160 + 150*gSinArray[(loop+480) % 720];
  241.     theTriangle[2].z = 0.25;
  242.     theTriangle[2].invW = 1.0;
  243.     theTriangle[2].a = 1;
  244.     theTriangle[2].r = 0.0;
  245.     theTriangle[2].g = 0.0;
  246.     theTriangle[2].b = 1.0;    
  247.  
  248.     // Render the triangle.
  249.     QARenderStart (theContext, NULL, NULL);
  250.     QADrawTriGouraud (theContext, &theTriangle[0], &theTriangle[1], &theTriangle[2], kQATriFlags_None);
  251.     QARenderEnd(theContext, NULL);    
  252.     
  253.     // Increment our loop position 2.5 degrees
  254.     loop = (loop+5) % 720;
  255.     }
  256.     
  257.     error:
  258.     // Either we got an error or the user finished.  In any case, tear everything down and return
  259.     
  260.     if (theContext != NULL)
  261.         QADrawContextDelete (theContext);
  262.     if (theWindow != NULL)
  263.         DisposeWindow(theWindow);
  264.     return;
  265. }
  266.  
  267.